{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "assert sys.version_info >= (3, 5)\n",
    "import numpy as np\n",
    "%matplotlib inline\n",
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "mpl.rc('axes', labelsize=14)\n",
    "mpl.rc('xtick', labelsize=12)\n",
    "mpl.rc('ytick', labelsize=12)\n",
    "import tensorflow as tf\n",
    "from tensorflow import keras\n",
    "import pandas as pd\n",
    "from scipy import special\n",
    "from tensorflow.keras import layers\n",
    "import itertools\n",
    "np.random.seed(42)\n",
    "tf.random.set_seed(42)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "M = 16\n",
    "k = int(np.log2(M))\n",
    "n = 1\n",
    "TRAINING_SNR = 7\n",
    "BINARY_INP = True\n",
    "rayleigh = False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def EbNo_to_noise(ebnodb):\n",
    "    '''Transform EbNo[dB]/snr to noise power'''\n",
    "    ebno = 10**(ebnodb/10)\n",
    "    noise_std = 1/np.sqrt(2*(k/n)*ebno) \n",
    "    return noise_std\n",
    "\n",
    "def SNR_to_noise(snrdb):\n",
    "    '''Transform EbNo[dB]/snr to noise power'''\n",
    "    snr = 10**(snrdb/10)\n",
    "    noise_std = 1/np.sqrt(2*snr)\n",
    "    return noise_std"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# From https://colab.research.google.com/github/google-research/google-research/blob/master/vbmi/vbmi_demo.ipynb#scrollTo=LwSIGeXlD11E\n",
    "# concatenated critic\n",
    "\n",
    "class NN_function(tf.keras.Model):\n",
    "    def __init__(self, hidden_dim, layers, activation, **extra_kwargs):\n",
    "        super(NN_function, self).__init__()\n",
    "        self._f = tf.keras.Sequential(\n",
    "          [tf.keras.layers.Dense(hidden_dim, activation) for _ in range(layers)] +\n",
    "          [tf.keras.layers.Dense(1)])\n",
    "\n",
    "    def call(self, x, y):\n",
    "        batch_size = tf.shape(x)[0]\n",
    "        x_tiled = tf.tile(x[None, :],  (batch_size, 1, 1))\n",
    "        y_tiled = tf.tile(y[:, None],  (1, batch_size, 1))\n",
    "        xy_pairs = tf.reshape(tf.concat((x_tiled, y_tiled), axis=2), [batch_size * batch_size, -1])\n",
    "        scores = self._f(xy_pairs)\n",
    "        return tf.transpose(tf.reshape(scores, [batch_size, batch_size]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "critic_params = {\n",
    "    'layers': 2,\n",
    "    'hidden_dim': 256,\n",
    "    'activation': 'relu',\n",
    "}\n",
    "\n",
    "def MINE(scores):  \n",
    "    def marg(x):\n",
    "        batch_size = x.shape[0]\n",
    "        marg_ = tf.reduce_mean(tf.exp(x - tf.linalg.tensor_diag(np.inf * tf.ones(batch_size))))\n",
    "        return marg_*((batch_size*batch_size)/(batch_size*(batch_size-1.)))\n",
    "    joint_term = tf.reduce_mean(tf.linalg.diag_part(scores))\n",
    "    marg_term = marg(scores)\n",
    "    return joint_term - tf.math.log(marg_term)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "noise_std = EbNo_to_noise(TRAINING_SNR)\n",
    "# custom functions / layers without weights\n",
    "norm_layer = keras.layers.Lambda(lambda x: tf.divide(x,tf.sqrt(2*tf.reduce_mean(tf.square(x)))))\n",
    "shape_layer = keras.layers.Lambda(lambda x: tf.reshape(x, shape=[-1,2,n]))\n",
    "shape_layer2 = keras.layers.Lambda(lambda x: tf.reshape(x, shape=[-1,2*n]))\n",
    "channel_layer = keras.layers.Lambda(lambda x: \n",
    "                    x + tf.random.normal(tf.shape(x), mean=0.0, stddev=noise_std))\n",
    "\n",
    "def sample_Rayleigh_channel(x, noise_std):\n",
    "    h_sample = (1/np.sqrt(2))*tf.sqrt(tf.random.normal(tf.shape(x))**2+tf.random.normal(tf.shape(x))**2)\n",
    "    z_sample = tf.random.normal(tf.shape(x), stddev = noise_std)\n",
    "    y_sample = x + tf.divide(z_sample,h_sample)\n",
    "    return tf.cast(y_sample, tf.float32)\n",
    "\n",
    "rayleigh_channel_layer = keras.layers.Lambda(lambda x: sample_Rayleigh_channel(x,noise_std))\n",
    "\n",
    "if rayleigh:\n",
    "    channel = keras.models.Sequential([rayleigh_channel_layer])\n",
    "else:\n",
    "    channel = keras.models.Sequential([channel_layer])\n",
    "\n",
    "if BINARY_INP:\n",
    "    encoder = keras.models.Sequential([\n",
    "            keras.layers.InputLayer(input_shape=[k]),\n",
    "            keras.layers.Dense(2*k, activation=\"elu\"),\n",
    "            keras.layers.Dense(2*k, activation=\"elu\"),\n",
    "            keras.layers.Dense(2*n, activation=None),\n",
    "            shape_layer,\n",
    "            norm_layer])\n",
    "    \n",
    "    decoder = keras.models.Sequential([\n",
    "                keras.layers.InputLayer(input_shape=[2,n]),\n",
    "                shape_layer2,\n",
    "                keras.layers.Dense(2*k , activation=\"elu\"),\n",
    "                keras.layers.Dense(2*k, activation=\"elu\"),\n",
    "                keras.layers.Dense(k, activation='sigmoid')\n",
    "                ])\n",
    "else:\n",
    "    encoder = keras.models.Sequential([\n",
    "            keras.layers.Embedding(M, M, embeddings_initializer='glorot_normal', input_length=1),\n",
    "            keras.layers.Dense(M, activation=\"elu\"),\n",
    "            keras.layers.Dense(2*n, activation=None),\n",
    "            shape_layer,\n",
    "            norm_layer])\n",
    "    \n",
    "    decoder = keras.models.Sequential([\n",
    "                keras.layers.InputLayer(input_shape=[2,n]),\n",
    "                shape_layer2,\n",
    "                keras.layers.Dense(M, activation=\"elu\"),\n",
    "                keras.layers.Dense(M, activation=\"softmax\")\n",
    "                ])\n",
    "\n",
    "autoencoder = keras.models.Sequential([encoder, channel, decoder])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def B_Ber_m(input_msg, msg):\n",
    "    '''Calculate the Batch Bit Error Rate'''\n",
    "    batch_size = input_msg.shape[0]\n",
    "    if BINARY_INP:\n",
    "        pred_error = tf.not_equal(input_msg, tf.round(msg))\n",
    "        pred_error_msg = tf.reduce_max(tf.cast(pred_error, tf.float32), axis=1)\n",
    "        bber = tf.reduce_mean(pred_error_msg)\n",
    "    else:\n",
    "        pred_error = tf.not_equal(tf.reshape(input_msg, shape=(-1,batch_size)), tf.argmax(msg, 1))\n",
    "        bber = tf.reduce_mean(tf.cast(pred_error, tf.float32))\n",
    "    return bber"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "def random_sample(batch_size=32, k=4):\n",
    "    if BINARY_INP:\n",
    "        msg = np.random.randint(2, size=(batch_size,k))\n",
    "    else:\n",
    "        msg = np.random.randint(M, size=(batch_size,1))\n",
    "    return msg"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test_encoding(M=16, n=1):\n",
    "    if BINARY_INP:\n",
    "        inp = np.array([list(i) for i in itertools.product([0, 1], repeat=int(np.log2(M)))])\n",
    "    else:\n",
    "        inp = np.arange(0,M)\n",
    "    coding = encoder.predict(inp)\n",
    "    fig = plt.figure(figsize=(4,4))\n",
    "    plt.plot(coding[:,0], coding[:, 1], \"b.\")\n",
    "    plt.xlabel(\"$x_1$\", fontsize=18)\n",
    "    plt.ylabel(\"$x_2$\", fontsize=18, rotation=0)\n",
    "    plt.grid(True)\n",
    "    plt.gca().set_ylim(-2, 2)\n",
    "    plt.gca().set_xlim(-2, 2)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test_noisy_codeword(data):\n",
    "    rcvd_word = data[1:2000]\n",
    "    fig = plt.figure(figsize=(4,4))\n",
    "    plt.plot(rcvd_word[:,0], rcvd_word[:, 1], \"b.\")\n",
    "    plt.xlabel(\"$x_1$\", fontsize=18)\n",
    "    plt.ylabel(\"$x_2$\", fontsize=18, rotation=0)\n",
    "    plt.grid(True)\n",
    "    plt.gca().set_ylim(-2, 2)\n",
    "    plt.gca().set_xlim(-2, 2)\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "if BINARY_INP:\n",
    "    loss_fn = tf.keras.losses.BinaryCrossentropy()\n",
    "else:\n",
    "    loss_fn = keras.losses.SparseCategoricalCrossentropy()\n",
    "    \n",
    "mean_loss = keras.metrics.Mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_loss(step, epoch, mean_loss, X_batch, y_pred, plot_encoding):\n",
    "    template = 'Iteration: {}, Epoch: {}, Loss: {:.5f}, Batch_BER: {:.5f}'\n",
    "    if step % 10 == 0:\n",
    "        print(template.format(step, epoch, mean_loss.result(), B_Ber_m(X_batch, y_pred)))\n",
    "        if plot_encoding:\n",
    "            test_encoding()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_batch_loss(epoch, mean_loss, X_batch, y_pred):\n",
    "        template_outer_loop = 'Interim result for Epoch: {}, Loss: {:.5f}, Batch_BER: {:.5f}'\n",
    "        print(template_outer_loop.format(epoch, mean_loss.result(), B_Ber_m(X_batch, y_pred)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_mi(NN_estimation, n_epochs=5, n_steps=20, batch_size=200, learning_rate=0.005):\n",
    "    optimizer_mi = keras.optimizers.Nadam(lr=learning_rate)\n",
    "    for epoch in range(1, n_epochs + 1): \n",
    "        print(\"Training in Epoch {}/{}\".format(epoch, n_epochs)) \n",
    "        for step in range(1, n_steps + 1):\n",
    "            X_batch = random_sample(batch_size, k)\n",
    "            with tf.GradientTape() as tape:\n",
    "                x_enc = encoder(X_batch, training=True)\n",
    "                y_recv = channel(x_enc)\n",
    "                x = tf.reshape(x_enc, shape=[batch_size,2*n])\n",
    "                y = tf.reshape(y_recv, shape=[batch_size,2*n])\n",
    "                score = NN_estimation(x,y)\n",
    "                loss = -MINE(score)\n",
    "                gradients = tape.gradient(loss, NN_estimation.trainable_variables) \n",
    "                optimizer_mi.apply_gradients(zip(gradients, NN_estimation.trainable_variables))\n",
    "            mi_avg = -mean_loss(loss)\n",
    "        print('Epoch: {}, Mi is {}'.format(epoch, mi_avg))\n",
    "        mean_loss.reset_states()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_decoder(n_epochs=5, n_steps=20, batch_size=200, learning_rate=0.005, plot_encoding=True):\n",
    "    optimizer_ae = keras.optimizers.Nadam(lr=learning_rate)\n",
    "    for epoch in range(1, n_epochs + 1): \n",
    "        print(\"Training Bob in Epoch {}/{}\".format(epoch, n_epochs)) \n",
    "        for step in range(1, n_steps + 1):\n",
    "            X_batch  = random_sample(batch_size, k)\n",
    "            with tf.GradientTape() as tape:\n",
    "                y_pred = autoencoder(X_batch, training=True)\n",
    "                loss = tf.reduce_mean(loss_fn(X_batch, y_pred))\n",
    "                gradients = tape.gradient(loss, decoder.trainable_variables) \n",
    "                optimizer_ae.apply_gradients(zip(gradients, decoder.trainable_variables)) \n",
    "            mean_loss(loss)\n",
    "            plot_loss(step, epoch, mean_loss, X_batch, y_pred, plot_encoding)\n",
    "        plot_batch_loss(epoch, mean_loss, X_batch, y_pred) \n",
    "        mean_loss.reset_states()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_encoder(NN_estimation, n_epochs=5, n_steps=20, batch_size=200, learning_rate=0.05):\n",
    "    optimizer_mi = keras.optimizers.Nadam(lr=0.005)\n",
    "    optimizer_ae = keras.optimizers.Nadam(lr=learning_rate)\n",
    "    for epoch in range(1, n_epochs + 1): \n",
    "        print(\"Training Bob in Epoch {}/{}\".format(epoch, n_epochs)) \n",
    "        for step in range(1, n_steps + 1):\n",
    "            X_batch  = random_sample(batch_size, k)\n",
    "            with tf.GradientTape() as tape:\n",
    "                x_enc = encoder(X_batch, training=True)\n",
    "                y_recv = tf.grad_pass_through(channel)(x_enc) #forward pass:channel; backward pass Identity\n",
    "                x = tf.reshape(x_enc, shape=[batch_size,2*n])\n",
    "                y = tf.reshape(y_recv, shape=[batch_size,2*n])\n",
    "                score = NN_estimation(x,y)\n",
    "                loss = -MINE(score)\n",
    "                gradients = tape.gradient(loss, encoder.trainable_variables) \n",
    "                optimizer_ae.apply_gradients(zip(gradients, encoder.trainable_variables))\n",
    "            mi_avg = -mean_loss(loss)\n",
    "        with tf.GradientTape() as tape:\n",
    "            X_batch  = random_sample(batch_size, k) \n",
    "            x_enc = encoder(X_batch, training=True)\n",
    "            y_recv = channel(x_enc)\n",
    "            x = tf.reshape(x_enc, shape=[batch_size,2*n])\n",
    "            y = tf.reshape(y_recv, shape=[batch_size,2*n])\n",
    "            score = NN_estimation(x,y)\n",
    "            loss = -MINE(score)\n",
    "            gradients = tape.gradient(loss, NN_estimation.trainable_variables) \n",
    "            optimizer_mi.apply_gradients(zip(gradients, NN_estimation.trainable_variables))\n",
    "        print('Epoch: {}, Mi is {}'.format(epoch, mi_avg))\n",
    "       # test_encoding(M, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def Test_AE():\n",
    "    '''Calculate Bit Error for varying SNRs'''\n",
    "    snr_range = np.linspace(0, 15, 31)\n",
    "    bber_vec = [None] * len(snr_range)\n",
    "        \n",
    "    for db in range(len(snr_range)):\n",
    "        for it in range(1,1000):\n",
    "            noise_std = EbNo_to_noise(snr_range[db])\n",
    "            X_batch  = random_sample(500, k)\n",
    "            code_word = encoder(X_batch)\n",
    "            if rayleigh:\n",
    "                rcvd_word = sample_Rayleigh_channel(code_word, noise_std)\n",
    "            else:\n",
    "                rcvd_word = code_word + tf.random.normal(tf.shape(code_word), mean=0.0, stddev=noise_std)\n",
    "            dcoded_msg = decoder(rcvd_word)\n",
    "            bber = B_Ber_m(X_batch, dcoded_msg)\n",
    "            bber_avg = mean_loss(bber)\n",
    "        bber_vec[db] = bber_avg\n",
    "        mean_loss.reset_states()\n",
    "        if (db % 6 == 0) & (db > 0):\n",
    "            print(f'Progress: {db} of {30} parts')\n",
    "\n",
    "    return (snr_range, bber_vec)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training in Epoch 1/1\n",
      "Epoch: 1, Mi is 1.9063373804092407\n",
      "Training Bob in Epoch 1/5\n",
      "Epoch: 1, Mi is 2.430373430252075\n",
      "Training Bob in Epoch 2/5\n",
      "Epoch: 2, Mi is 2.4276349544525146\n",
      "Training Bob in Epoch 3/5\n",
      "Epoch: 3, Mi is 2.4402523040771484\n",
      "Training Bob in Epoch 4/5\n",
      "Epoch: 4, Mi is 2.4549336433410645\n",
      "Training Bob in Epoch 5/5\n",
      "Epoch: 5, Mi is 2.471193313598633\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 288x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training Bob in Epoch 1/5\n",
      "Epoch: 1, Mi is 2.4762895107269287\n",
      "Training Bob in Epoch 2/5\n",
      "Epoch: 2, Mi is 2.485874652862549\n",
      "Training Bob in Epoch 3/5\n",
      "Epoch: 3, Mi is 2.4936628341674805\n",
      "Training Bob in Epoch 4/5\n",
      "Epoch: 4, Mi is 2.498422622680664\n",
      "Training Bob in Epoch 5/5\n",
      "Epoch: 5, Mi is 2.5010550022125244\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 288x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training Bob in Epoch 1/5\n",
      "Iteration: 10, Epoch: 1, Loss: -2.49318, Batch_BER: 0.74200\n",
      "Iteration: 20, Epoch: 1, Loss: -2.48567, Batch_BER: 0.72200\n",
      "Iteration: 30, Epoch: 1, Loss: -2.47842, Batch_BER: 0.56000\n",
      "Iteration: 40, Epoch: 1, Loss: -2.47131, Batch_BER: 0.48200\n",
      "Iteration: 50, Epoch: 1, Loss: -2.46423, Batch_BER: 0.52800\n",
      "Iteration: 60, Epoch: 1, Loss: -2.45720, Batch_BER: 0.52800\n",
      "Iteration: 70, Epoch: 1, Loss: -2.45020, Batch_BER: 0.54000\n",
      "Iteration: 80, Epoch: 1, Loss: -2.44325, Batch_BER: 0.51600\n",
      "Iteration: 90, Epoch: 1, Loss: -2.43634, Batch_BER: 0.52600\n",
      "Iteration: 100, Epoch: 1, Loss: -2.42948, Batch_BER: 0.53200\n",
      "Iteration: 110, Epoch: 1, Loss: -2.42266, Batch_BER: 0.50000\n",
      "Iteration: 120, Epoch: 1, Loss: -2.41589, Batch_BER: 0.51600\n",
      "Iteration: 130, Epoch: 1, Loss: -2.40915, Batch_BER: 0.53400\n",
      "Iteration: 140, Epoch: 1, Loss: -2.40245, Batch_BER: 0.48600\n",
      "Iteration: 150, Epoch: 1, Loss: -2.39579, Batch_BER: 0.49600\n",
      "Iteration: 160, Epoch: 1, Loss: -2.38917, Batch_BER: 0.51400\n",
      "Iteration: 170, Epoch: 1, Loss: -2.38259, Batch_BER: 0.53800\n",
      "Iteration: 180, Epoch: 1, Loss: -2.37605, Batch_BER: 0.51400\n",
      "Iteration: 190, Epoch: 1, Loss: -2.36955, Batch_BER: 0.49400\n",
      "Iteration: 200, Epoch: 1, Loss: -2.36310, Batch_BER: 0.42000\n",
      "Iteration: 210, Epoch: 1, Loss: -2.35671, Batch_BER: 0.49800\n",
      "Iteration: 220, Epoch: 1, Loss: -2.35037, Batch_BER: 0.45600\n",
      "Iteration: 230, Epoch: 1, Loss: -2.34407, Batch_BER: 0.43600\n",
      "Iteration: 240, Epoch: 1, Loss: -2.33780, Batch_BER: 0.40800\n",
      "Iteration: 250, Epoch: 1, Loss: -2.33159, Batch_BER: 0.42600\n",
      "Iteration: 260, Epoch: 1, Loss: -2.32542, Batch_BER: 0.37600\n",
      "Iteration: 270, Epoch: 1, Loss: -2.31931, Batch_BER: 0.42000\n",
      "Iteration: 280, Epoch: 1, Loss: -2.31325, Batch_BER: 0.35600\n",
      "Iteration: 290, Epoch: 1, Loss: -2.30725, Batch_BER: 0.35400\n",
      "Iteration: 300, Epoch: 1, Loss: -2.30129, Batch_BER: 0.34600\n",
      "Iteration: 310, Epoch: 1, Loss: -2.29536, Batch_BER: 0.35200\n",
      "Iteration: 320, Epoch: 1, Loss: -2.28951, Batch_BER: 0.31800\n",
      "Iteration: 330, Epoch: 1, Loss: -2.28368, Batch_BER: 0.32000\n",
      "Iteration: 340, Epoch: 1, Loss: -2.27793, Batch_BER: 0.28000\n",
      "Iteration: 350, Epoch: 1, Loss: -2.27220, Batch_BER: 0.27200\n",
      "Iteration: 360, Epoch: 1, Loss: -2.26651, Batch_BER: 0.27600\n",
      "Iteration: 370, Epoch: 1, Loss: -2.26084, Batch_BER: 0.30200\n",
      "Iteration: 380, Epoch: 1, Loss: -2.25519, Batch_BER: 0.27000\n",
      "Iteration: 390, Epoch: 1, Loss: -2.24962, Batch_BER: 0.19800\n",
      "Iteration: 400, Epoch: 1, Loss: -2.24408, Batch_BER: 0.24200\n",
      "Interim result for Epoch: 1, Loss: -2.24408, Batch_BER: 0.24200\n",
      "Training Bob in Epoch 2/5\n",
      "Iteration: 10, Epoch: 2, Loss: 0.18413, Batch_BER: 0.25000\n",
      "Iteration: 20, Epoch: 2, Loss: 0.18375, Batch_BER: 0.20400\n",
      "Iteration: 30, Epoch: 2, Loss: 0.18755, Batch_BER: 0.28000\n",
      "Iteration: 40, Epoch: 2, Loss: 0.18735, Batch_BER: 0.22800\n",
      "Iteration: 50, Epoch: 2, Loss: 0.18489, Batch_BER: 0.20800\n",
      "Iteration: 60, Epoch: 2, Loss: 0.18321, Batch_BER: 0.22600\n",
      "Iteration: 70, Epoch: 2, Loss: 0.18150, Batch_BER: 0.21600\n",
      "Iteration: 80, Epoch: 2, Loss: 0.18042, Batch_BER: 0.20200\n",
      "Iteration: 90, Epoch: 2, Loss: 0.17913, Batch_BER: 0.21400\n",
      "Iteration: 100, Epoch: 2, Loss: 0.17839, Batch_BER: 0.18800\n",
      "Iteration: 110, Epoch: 2, Loss: 0.17705, Batch_BER: 0.16600\n",
      "Iteration: 120, Epoch: 2, Loss: 0.17561, Batch_BER: 0.16800\n",
      "Iteration: 130, Epoch: 2, Loss: 0.17422, Batch_BER: 0.16600\n",
      "Iteration: 140, Epoch: 2, Loss: 0.17329, Batch_BER: 0.17800\n",
      "Iteration: 150, Epoch: 2, Loss: 0.17213, Batch_BER: 0.19400\n",
      "Iteration: 160, Epoch: 2, Loss: 0.17123, Batch_BER: 0.17200\n",
      "Iteration: 170, Epoch: 2, Loss: 0.17038, Batch_BER: 0.19800\n",
      "Iteration: 180, Epoch: 2, Loss: 0.16952, Batch_BER: 0.15400\n",
      "Iteration: 190, Epoch: 2, Loss: 0.16868, Batch_BER: 0.16400\n",
      "Iteration: 200, Epoch: 2, Loss: 0.16806, Batch_BER: 0.15800\n",
      "Iteration: 210, Epoch: 2, Loss: 0.16721, Batch_BER: 0.16400\n",
      "Iteration: 220, Epoch: 2, Loss: 0.16639, Batch_BER: 0.17800\n",
      "Iteration: 230, Epoch: 2, Loss: 0.16565, Batch_BER: 0.14000\n",
      "Iteration: 240, Epoch: 2, Loss: 0.16525, Batch_BER: 0.19200\n",
      "Iteration: 250, Epoch: 2, Loss: 0.16481, Batch_BER: 0.16000\n",
      "Iteration: 260, Epoch: 2, Loss: 0.16397, Batch_BER: 0.15000\n",
      "Iteration: 270, Epoch: 2, Loss: 0.16350, Batch_BER: 0.17000\n",
      "Iteration: 280, Epoch: 2, Loss: 0.16281, Batch_BER: 0.13600\n",
      "Iteration: 290, Epoch: 2, Loss: 0.16257, Batch_BER: 0.19000\n",
      "Iteration: 300, Epoch: 2, Loss: 0.16197, Batch_BER: 0.16400\n",
      "Iteration: 310, Epoch: 2, Loss: 0.16156, Batch_BER: 0.15600\n",
      "Iteration: 320, Epoch: 2, Loss: 0.16104, Batch_BER: 0.17400\n",
      "Iteration: 330, Epoch: 2, Loss: 0.16069, Batch_BER: 0.16600\n",
      "Iteration: 340, Epoch: 2, Loss: 0.16002, Batch_BER: 0.12800\n",
      "Iteration: 350, Epoch: 2, Loss: 0.15962, Batch_BER: 0.14400\n",
      "Iteration: 360, Epoch: 2, Loss: 0.15912, Batch_BER: 0.16200\n",
      "Iteration: 370, Epoch: 2, Loss: 0.15887, Batch_BER: 0.20400\n",
      "Iteration: 380, Epoch: 2, Loss: 0.15837, Batch_BER: 0.16200\n",
      "Iteration: 390, Epoch: 2, Loss: 0.15791, Batch_BER: 0.15800\n",
      "Iteration: 400, Epoch: 2, Loss: 0.15764, Batch_BER: 0.18000\n",
      "Interim result for Epoch: 2, Loss: 0.15764, Batch_BER: 0.18000\n",
      "Training Bob in Epoch 3/5\n",
      "Iteration: 10, Epoch: 3, Loss: 0.13878, Batch_BER: 0.14000\n",
      "Iteration: 20, Epoch: 3, Loss: 0.13787, Batch_BER: 0.13000\n",
      "Iteration: 30, Epoch: 3, Loss: 0.13871, Batch_BER: 0.12400\n",
      "Iteration: 40, Epoch: 3, Loss: 0.13989, Batch_BER: 0.15800\n",
      "Iteration: 50, Epoch: 3, Loss: 0.14092, Batch_BER: 0.14200\n",
      "Iteration: 60, Epoch: 3, Loss: 0.14078, Batch_BER: 0.12600\n",
      "Iteration: 70, Epoch: 3, Loss: 0.14020, Batch_BER: 0.15400\n",
      "Iteration: 80, Epoch: 3, Loss: 0.14048, Batch_BER: 0.15000\n",
      "Iteration: 90, Epoch: 3, Loss: 0.14064, Batch_BER: 0.13800\n",
      "Iteration: 100, Epoch: 3, Loss: 0.14017, Batch_BER: 0.12200\n",
      "Iteration: 110, Epoch: 3, Loss: 0.13962, Batch_BER: 0.13200\n",
      "Iteration: 120, Epoch: 3, Loss: 0.13938, Batch_BER: 0.15200\n",
      "Iteration: 130, Epoch: 3, Loss: 0.13905, Batch_BER: 0.13000\n",
      "Iteration: 140, Epoch: 3, Loss: 0.13897, Batch_BER: 0.15200\n",
      "Iteration: 150, Epoch: 3, Loss: 0.13865, Batch_BER: 0.15000\n",
      "Iteration: 160, Epoch: 3, Loss: 0.13856, Batch_BER: 0.15000\n",
      "Iteration: 170, Epoch: 3, Loss: 0.13858, Batch_BER: 0.14600\n",
      "Iteration: 180, Epoch: 3, Loss: 0.13774, Batch_BER: 0.11400\n",
      "Iteration: 190, Epoch: 3, Loss: 0.13795, Batch_BER: 0.12600\n",
      "Iteration: 200, Epoch: 3, Loss: 0.13761, Batch_BER: 0.12000\n",
      "Iteration: 210, Epoch: 3, Loss: 0.13767, Batch_BER: 0.14400\n",
      "Iteration: 220, Epoch: 3, Loss: 0.13776, Batch_BER: 0.12800\n",
      "Iteration: 230, Epoch: 3, Loss: 0.13778, Batch_BER: 0.14200\n",
      "Iteration: 240, Epoch: 3, Loss: 0.13757, Batch_BER: 0.12600\n",
      "Iteration: 250, Epoch: 3, Loss: 0.13751, Batch_BER: 0.13200\n",
      "Iteration: 260, Epoch: 3, Loss: 0.13714, Batch_BER: 0.14800\n",
      "Iteration: 270, Epoch: 3, Loss: 0.13701, Batch_BER: 0.14200\n",
      "Iteration: 280, Epoch: 3, Loss: 0.13687, Batch_BER: 0.12400\n",
      "Iteration: 290, Epoch: 3, Loss: 0.13672, Batch_BER: 0.12000\n",
      "Iteration: 300, Epoch: 3, Loss: 0.13662, Batch_BER: 0.12000\n",
      "Iteration: 310, Epoch: 3, Loss: 0.13659, Batch_BER: 0.13800\n",
      "Iteration: 320, Epoch: 3, Loss: 0.13646, Batch_BER: 0.12200\n",
      "Iteration: 330, Epoch: 3, Loss: 0.13678, Batch_BER: 0.17400\n",
      "Iteration: 340, Epoch: 3, Loss: 0.13675, Batch_BER: 0.12600\n",
      "Iteration: 350, Epoch: 3, Loss: 0.13668, Batch_BER: 0.10600\n",
      "Iteration: 360, Epoch: 3, Loss: 0.13660, Batch_BER: 0.13400\n",
      "Iteration: 370, Epoch: 3, Loss: 0.13639, Batch_BER: 0.10800\n",
      "Iteration: 380, Epoch: 3, Loss: 0.13612, Batch_BER: 0.11600\n",
      "Iteration: 390, Epoch: 3, Loss: 0.13598, Batch_BER: 0.09800\n",
      "Iteration: 400, Epoch: 3, Loss: 0.13600, Batch_BER: 0.11600\n",
      "Interim result for Epoch: 3, Loss: 0.13600, Batch_BER: 0.11600\n",
      "Training Bob in Epoch 4/5\n",
      "Iteration: 10, Epoch: 4, Loss: 0.12816, Batch_BER: 0.12000\n",
      "Iteration: 20, Epoch: 4, Loss: 0.13446, Batch_BER: 0.11400\n",
      "Iteration: 30, Epoch: 4, Loss: 0.13308, Batch_BER: 0.12600\n",
      "Iteration: 40, Epoch: 4, Loss: 0.13366, Batch_BER: 0.15400\n",
      "Iteration: 50, Epoch: 4, Loss: 0.13353, Batch_BER: 0.13800\n",
      "Iteration: 60, Epoch: 4, Loss: 0.13260, Batch_BER: 0.11400\n",
      "Iteration: 70, Epoch: 4, Loss: 0.13202, Batch_BER: 0.12200\n",
      "Iteration: 80, Epoch: 4, Loss: 0.13119, Batch_BER: 0.12800\n",
      "Iteration: 90, Epoch: 4, Loss: 0.13089, Batch_BER: 0.12600\n",
      "Iteration: 100, Epoch: 4, Loss: 0.13014, Batch_BER: 0.10400\n",
      "Iteration: 110, Epoch: 4, Loss: 0.12986, Batch_BER: 0.13200\n",
      "Iteration: 120, Epoch: 4, Loss: 0.12985, Batch_BER: 0.13800\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 130, Epoch: 4, Loss: 0.12953, Batch_BER: 0.12200\n",
      "Iteration: 140, Epoch: 4, Loss: 0.12920, Batch_BER: 0.12000\n",
      "Iteration: 150, Epoch: 4, Loss: 0.12938, Batch_BER: 0.13800\n",
      "Iteration: 160, Epoch: 4, Loss: 0.12901, Batch_BER: 0.12800\n",
      "Iteration: 170, Epoch: 4, Loss: 0.12933, Batch_BER: 0.15200\n",
      "Iteration: 180, Epoch: 4, Loss: 0.12998, Batch_BER: 0.14200\n",
      "Iteration: 190, Epoch: 4, Loss: 0.13016, Batch_BER: 0.15400\n",
      "Iteration: 200, Epoch: 4, Loss: 0.13032, Batch_BER: 0.11600\n",
      "Iteration: 210, Epoch: 4, Loss: 0.13049, Batch_BER: 0.13600\n",
      "Iteration: 220, Epoch: 4, Loss: 0.13028, Batch_BER: 0.11000\n",
      "Iteration: 230, Epoch: 4, Loss: 0.13011, Batch_BER: 0.15400\n",
      "Iteration: 240, Epoch: 4, Loss: 0.13012, Batch_BER: 0.10600\n",
      "Iteration: 250, Epoch: 4, Loss: 0.13005, Batch_BER: 0.13200\n",
      "Iteration: 260, Epoch: 4, Loss: 0.12997, Batch_BER: 0.13800\n",
      "Iteration: 270, Epoch: 4, Loss: 0.12997, Batch_BER: 0.11200\n",
      "Iteration: 280, Epoch: 4, Loss: 0.12999, Batch_BER: 0.12600\n",
      "Iteration: 290, Epoch: 4, Loss: 0.12997, Batch_BER: 0.14800\n",
      "Iteration: 300, Epoch: 4, Loss: 0.12962, Batch_BER: 0.09800\n",
      "Iteration: 310, Epoch: 4, Loss: 0.12947, Batch_BER: 0.11800\n",
      "Iteration: 320, Epoch: 4, Loss: 0.12925, Batch_BER: 0.12000\n",
      "Iteration: 330, Epoch: 4, Loss: 0.12921, Batch_BER: 0.14200\n",
      "Iteration: 340, Epoch: 4, Loss: 0.12906, Batch_BER: 0.11800\n",
      "Iteration: 350, Epoch: 4, Loss: 0.12901, Batch_BER: 0.17000\n",
      "Iteration: 360, Epoch: 4, Loss: 0.12891, Batch_BER: 0.12200\n",
      "Iteration: 370, Epoch: 4, Loss: 0.12896, Batch_BER: 0.11800\n",
      "Iteration: 380, Epoch: 4, Loss: 0.12876, Batch_BER: 0.10000\n",
      "Iteration: 390, Epoch: 4, Loss: 0.12862, Batch_BER: 0.12600\n",
      "Iteration: 400, Epoch: 4, Loss: 0.12842, Batch_BER: 0.09600\n",
      "Interim result for Epoch: 4, Loss: 0.12842, Batch_BER: 0.09600\n",
      "Training Bob in Epoch 5/5\n",
      "Iteration: 10, Epoch: 5, Loss: 0.12720, Batch_BER: 0.13400\n",
      "Iteration: 20, Epoch: 5, Loss: 0.12304, Batch_BER: 0.13400\n",
      "Iteration: 30, Epoch: 5, Loss: 0.12340, Batch_BER: 0.12800\n",
      "Iteration: 40, Epoch: 5, Loss: 0.12260, Batch_BER: 0.12800\n",
      "Iteration: 50, Epoch: 5, Loss: 0.12362, Batch_BER: 0.12000\n",
      "Iteration: 60, Epoch: 5, Loss: 0.12339, Batch_BER: 0.10800\n",
      "Iteration: 70, Epoch: 5, Loss: 0.12350, Batch_BER: 0.15800\n",
      "Iteration: 80, Epoch: 5, Loss: 0.12313, Batch_BER: 0.13200\n",
      "Iteration: 90, Epoch: 5, Loss: 0.12265, Batch_BER: 0.11400\n",
      "Iteration: 100, Epoch: 5, Loss: 0.12288, Batch_BER: 0.10000\n",
      "Iteration: 110, Epoch: 5, Loss: 0.12352, Batch_BER: 0.12600\n",
      "Iteration: 120, Epoch: 5, Loss: 0.12342, Batch_BER: 0.12400\n",
      "Iteration: 130, Epoch: 5, Loss: 0.12383, Batch_BER: 0.13400\n",
      "Iteration: 140, Epoch: 5, Loss: 0.12357, Batch_BER: 0.12200\n",
      "Iteration: 150, Epoch: 5, Loss: 0.12337, Batch_BER: 0.09600\n",
      "Iteration: 160, Epoch: 5, Loss: 0.12368, Batch_BER: 0.10400\n",
      "Iteration: 170, Epoch: 5, Loss: 0.12296, Batch_BER: 0.11200\n",
      "Iteration: 180, Epoch: 5, Loss: 0.12300, Batch_BER: 0.11800\n",
      "Iteration: 190, Epoch: 5, Loss: 0.12312, Batch_BER: 0.11400\n",
      "Iteration: 200, Epoch: 5, Loss: 0.12289, Batch_BER: 0.14200\n",
      "Iteration: 210, Epoch: 5, Loss: 0.12301, Batch_BER: 0.13200\n",
      "Iteration: 220, Epoch: 5, Loss: 0.12303, Batch_BER: 0.12200\n",
      "Iteration: 230, Epoch: 5, Loss: 0.12305, Batch_BER: 0.09600\n",
      "Iteration: 240, Epoch: 5, Loss: 0.12278, Batch_BER: 0.11000\n",
      "Iteration: 250, Epoch: 5, Loss: 0.12256, Batch_BER: 0.10600\n",
      "Iteration: 260, Epoch: 5, Loss: 0.12226, Batch_BER: 0.11800\n",
      "Iteration: 270, Epoch: 5, Loss: 0.12230, Batch_BER: 0.11400\n",
      "Iteration: 280, Epoch: 5, Loss: 0.12215, Batch_BER: 0.11600\n",
      "Iteration: 290, Epoch: 5, Loss: 0.12235, Batch_BER: 0.11800\n",
      "Iteration: 300, Epoch: 5, Loss: 0.12243, Batch_BER: 0.11000\n",
      "Iteration: 310, Epoch: 5, Loss: 0.12263, Batch_BER: 0.11400\n",
      "Iteration: 320, Epoch: 5, Loss: 0.12255, Batch_BER: 0.12600\n",
      "Iteration: 330, Epoch: 5, Loss: 0.12259, Batch_BER: 0.10200\n",
      "Iteration: 340, Epoch: 5, Loss: 0.12268, Batch_BER: 0.13200\n",
      "Iteration: 350, Epoch: 5, Loss: 0.12263, Batch_BER: 0.10800\n",
      "Iteration: 360, Epoch: 5, Loss: 0.12255, Batch_BER: 0.12000\n",
      "Iteration: 370, Epoch: 5, Loss: 0.12231, Batch_BER: 0.10400\n",
      "Iteration: 380, Epoch: 5, Loss: 0.12239, Batch_BER: 0.12200\n",
      "Iteration: 390, Epoch: 5, Loss: 0.12233, Batch_BER: 0.09800\n",
      "Iteration: 400, Epoch: 5, Loss: 0.12223, Batch_BER: 0.10800\n",
      "Interim result for Epoch: 5, Loss: 0.12223, Batch_BER: 0.10800\n",
      "Training Bob in Epoch 1/4\n",
      "Iteration: 10, Epoch: 1, Loss: 0.12043, Batch_BER: 0.12200\n",
      "Iteration: 20, Epoch: 1, Loss: 0.11975, Batch_BER: 0.11200\n",
      "Iteration: 30, Epoch: 1, Loss: 0.11746, Batch_BER: 0.11400\n",
      "Iteration: 40, Epoch: 1, Loss: 0.11878, Batch_BER: 0.13600\n",
      "Iteration: 50, Epoch: 1, Loss: 0.11991, Batch_BER: 0.12200\n",
      "Iteration: 60, Epoch: 1, Loss: 0.12071, Batch_BER: 0.11000\n",
      "Iteration: 70, Epoch: 1, Loss: 0.12058, Batch_BER: 0.10800\n",
      "Iteration: 80, Epoch: 1, Loss: 0.12051, Batch_BER: 0.08800\n",
      "Iteration: 90, Epoch: 1, Loss: 0.12033, Batch_BER: 0.12000\n",
      "Iteration: 100, Epoch: 1, Loss: 0.11995, Batch_BER: 0.07600\n",
      "Iteration: 110, Epoch: 1, Loss: 0.11986, Batch_BER: 0.10800\n",
      "Iteration: 120, Epoch: 1, Loss: 0.11927, Batch_BER: 0.11600\n",
      "Iteration: 130, Epoch: 1, Loss: 0.11970, Batch_BER: 0.12200\n",
      "Iteration: 140, Epoch: 1, Loss: 0.11937, Batch_BER: 0.07200\n",
      "Iteration: 150, Epoch: 1, Loss: 0.11973, Batch_BER: 0.13200\n",
      "Iteration: 160, Epoch: 1, Loss: 0.11961, Batch_BER: 0.12200\n",
      "Iteration: 170, Epoch: 1, Loss: 0.11912, Batch_BER: 0.12800\n",
      "Iteration: 180, Epoch: 1, Loss: 0.11894, Batch_BER: 0.08000\n",
      "Iteration: 190, Epoch: 1, Loss: 0.11864, Batch_BER: 0.09400\n",
      "Iteration: 200, Epoch: 1, Loss: 0.11871, Batch_BER: 0.12600\n",
      "Iteration: 210, Epoch: 1, Loss: 0.11848, Batch_BER: 0.10600\n",
      "Iteration: 220, Epoch: 1, Loss: 0.11823, Batch_BER: 0.11600\n",
      "Iteration: 230, Epoch: 1, Loss: 0.11797, Batch_BER: 0.10400\n",
      "Iteration: 240, Epoch: 1, Loss: 0.11780, Batch_BER: 0.11200\n",
      "Iteration: 250, Epoch: 1, Loss: 0.11775, Batch_BER: 0.11000\n",
      "Iteration: 260, Epoch: 1, Loss: 0.11791, Batch_BER: 0.13400\n",
      "Iteration: 270, Epoch: 1, Loss: 0.11797, Batch_BER: 0.11800\n",
      "Iteration: 280, Epoch: 1, Loss: 0.11818, Batch_BER: 0.12400\n",
      "Iteration: 290, Epoch: 1, Loss: 0.11798, Batch_BER: 0.11400\n",
      "Iteration: 300, Epoch: 1, Loss: 0.11793, Batch_BER: 0.12000\n",
      "Iteration: 310, Epoch: 1, Loss: 0.11802, Batch_BER: 0.10200\n",
      "Iteration: 320, Epoch: 1, Loss: 0.11808, Batch_BER: 0.10800\n",
      "Iteration: 330, Epoch: 1, Loss: 0.11788, Batch_BER: 0.07000\n",
      "Iteration: 340, Epoch: 1, Loss: 0.11791, Batch_BER: 0.08600\n",
      "Iteration: 350, Epoch: 1, Loss: 0.11792, Batch_BER: 0.11200\n",
      "Iteration: 360, Epoch: 1, Loss: 0.11774, Batch_BER: 0.11200\n",
      "Iteration: 370, Epoch: 1, Loss: 0.11756, Batch_BER: 0.10600\n",
      "Iteration: 380, Epoch: 1, Loss: 0.11744, Batch_BER: 0.09000\n",
      "Iteration: 390, Epoch: 1, Loss: 0.11733, Batch_BER: 0.09400\n",
      "Iteration: 400, Epoch: 1, Loss: 0.11743, Batch_BER: 0.10000\n",
      "Interim result for Epoch: 1, Loss: 0.11743, Batch_BER: 0.10000\n",
      "Training Bob in Epoch 2/4\n",
      "Iteration: 10, Epoch: 2, Loss: 0.11076, Batch_BER: 0.08200\n",
      "Iteration: 20, Epoch: 2, Loss: 0.11348, Batch_BER: 0.11400\n",
      "Iteration: 30, Epoch: 2, Loss: 0.11457, Batch_BER: 0.09800\n",
      "Iteration: 40, Epoch: 2, Loss: 0.11542, Batch_BER: 0.10400\n",
      "Iteration: 50, Epoch: 2, Loss: 0.11492, Batch_BER: 0.09800\n",
      "Iteration: 60, Epoch: 2, Loss: 0.11633, Batch_BER: 0.12200\n",
      "Iteration: 70, Epoch: 2, Loss: 0.11591, Batch_BER: 0.08200\n",
      "Iteration: 80, Epoch: 2, Loss: 0.11541, Batch_BER: 0.12200\n",
      "Iteration: 90, Epoch: 2, Loss: 0.11524, Batch_BER: 0.10200\n",
      "Iteration: 100, Epoch: 2, Loss: 0.11472, Batch_BER: 0.08400\n",
      "Iteration: 110, Epoch: 2, Loss: 0.11508, Batch_BER: 0.08800\n",
      "Iteration: 120, Epoch: 2, Loss: 0.11542, Batch_BER: 0.12200\n",
      "Iteration: 130, Epoch: 2, Loss: 0.11521, Batch_BER: 0.11800\n",
      "Iteration: 140, Epoch: 2, Loss: 0.11487, Batch_BER: 0.10600\n",
      "Iteration: 150, Epoch: 2, Loss: 0.11475, Batch_BER: 0.10600\n",
      "Iteration: 160, Epoch: 2, Loss: 0.11518, Batch_BER: 0.13200\n",
      "Iteration: 170, Epoch: 2, Loss: 0.11493, Batch_BER: 0.08600\n",
      "Iteration: 180, Epoch: 2, Loss: 0.11488, Batch_BER: 0.10600\n",
      "Iteration: 190, Epoch: 2, Loss: 0.11501, Batch_BER: 0.11400\n",
      "Iteration: 200, Epoch: 2, Loss: 0.11528, Batch_BER: 0.12400\n",
      "Iteration: 210, Epoch: 2, Loss: 0.11530, Batch_BER: 0.09800\n",
      "Iteration: 220, Epoch: 2, Loss: 0.11543, Batch_BER: 0.10400\n",
      "Iteration: 230, Epoch: 2, Loss: 0.11538, Batch_BER: 0.11000\n",
      "Iteration: 240, Epoch: 2, Loss: 0.11545, Batch_BER: 0.10400\n",
      "Iteration: 250, Epoch: 2, Loss: 0.11526, Batch_BER: 0.11200\n",
      "Iteration: 260, Epoch: 2, Loss: 0.11494, Batch_BER: 0.10400\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 270, Epoch: 2, Loss: 0.11481, Batch_BER: 0.07400\n",
      "Iteration: 280, Epoch: 2, Loss: 0.11479, Batch_BER: 0.11800\n",
      "Iteration: 290, Epoch: 2, Loss: 0.11463, Batch_BER: 0.09200\n",
      "Iteration: 300, Epoch: 2, Loss: 0.11475, Batch_BER: 0.08000\n",
      "Iteration: 310, Epoch: 2, Loss: 0.11477, Batch_BER: 0.12600\n",
      "Iteration: 320, Epoch: 2, Loss: 0.11512, Batch_BER: 0.12200\n",
      "Iteration: 330, Epoch: 2, Loss: 0.11495, Batch_BER: 0.08000\n",
      "Iteration: 340, Epoch: 2, Loss: 0.11494, Batch_BER: 0.11000\n",
      "Iteration: 350, Epoch: 2, Loss: 0.11524, Batch_BER: 0.12400\n",
      "Iteration: 360, Epoch: 2, Loss: 0.11511, Batch_BER: 0.08600\n",
      "Iteration: 370, Epoch: 2, Loss: 0.11504, Batch_BER: 0.10400\n",
      "Iteration: 380, Epoch: 2, Loss: 0.11502, Batch_BER: 0.11200\n",
      "Iteration: 390, Epoch: 2, Loss: 0.11474, Batch_BER: 0.11800\n",
      "Iteration: 400, Epoch: 2, Loss: 0.11476, Batch_BER: 0.10000\n",
      "Interim result for Epoch: 2, Loss: 0.11476, Batch_BER: 0.10000\n",
      "Training Bob in Epoch 3/4\n",
      "Iteration: 10, Epoch: 3, Loss: 0.10982, Batch_BER: 0.09400\n",
      "Iteration: 20, Epoch: 3, Loss: 0.11051, Batch_BER: 0.08000\n",
      "Iteration: 30, Epoch: 3, Loss: 0.11049, Batch_BER: 0.11200\n",
      "Iteration: 40, Epoch: 3, Loss: 0.10991, Batch_BER: 0.10200\n",
      "Iteration: 50, Epoch: 3, Loss: 0.10995, Batch_BER: 0.12800\n",
      "Iteration: 60, Epoch: 3, Loss: 0.10999, Batch_BER: 0.09000\n",
      "Iteration: 70, Epoch: 3, Loss: 0.10980, Batch_BER: 0.10600\n",
      "Iteration: 80, Epoch: 3, Loss: 0.10994, Batch_BER: 0.09800\n",
      "Iteration: 90, Epoch: 3, Loss: 0.11012, Batch_BER: 0.09000\n",
      "Iteration: 100, Epoch: 3, Loss: 0.11076, Batch_BER: 0.08800\n",
      "Iteration: 110, Epoch: 3, Loss: 0.11097, Batch_BER: 0.12400\n",
      "Iteration: 120, Epoch: 3, Loss: 0.11024, Batch_BER: 0.12200\n",
      "Iteration: 130, Epoch: 3, Loss: 0.11057, Batch_BER: 0.11200\n",
      "Iteration: 140, Epoch: 3, Loss: 0.11059, Batch_BER: 0.09200\n",
      "Iteration: 150, Epoch: 3, Loss: 0.11059, Batch_BER: 0.10400\n",
      "Iteration: 160, Epoch: 3, Loss: 0.11050, Batch_BER: 0.10200\n",
      "Iteration: 170, Epoch: 3, Loss: 0.11080, Batch_BER: 0.11400\n",
      "Iteration: 180, Epoch: 3, Loss: 0.11072, Batch_BER: 0.09600\n",
      "Iteration: 190, Epoch: 3, Loss: 0.11097, Batch_BER: 0.10000\n",
      "Iteration: 200, Epoch: 3, Loss: 0.11111, Batch_BER: 0.09600\n",
      "Iteration: 210, Epoch: 3, Loss: 0.11118, Batch_BER: 0.09800\n",
      "Iteration: 220, Epoch: 3, Loss: 0.11149, Batch_BER: 0.10000\n",
      "Iteration: 230, Epoch: 3, Loss: 0.11157, Batch_BER: 0.08600\n",
      "Iteration: 240, Epoch: 3, Loss: 0.11148, Batch_BER: 0.08400\n",
      "Iteration: 250, Epoch: 3, Loss: 0.11132, Batch_BER: 0.09000\n",
      "Iteration: 260, Epoch: 3, Loss: 0.11144, Batch_BER: 0.12200\n",
      "Iteration: 270, Epoch: 3, Loss: 0.11150, Batch_BER: 0.11600\n",
      "Iteration: 280, Epoch: 3, Loss: 0.11153, Batch_BER: 0.10400\n",
      "Iteration: 290, Epoch: 3, Loss: 0.11121, Batch_BER: 0.08200\n",
      "Iteration: 300, Epoch: 3, Loss: 0.11125, Batch_BER: 0.07200\n",
      "Iteration: 310, Epoch: 3, Loss: 0.11123, Batch_BER: 0.12400\n",
      "Iteration: 320, Epoch: 3, Loss: 0.11121, Batch_BER: 0.10600\n",
      "Iteration: 330, Epoch: 3, Loss: 0.11128, Batch_BER: 0.10600\n",
      "Iteration: 340, Epoch: 3, Loss: 0.11122, Batch_BER: 0.09800\n",
      "Iteration: 350, Epoch: 3, Loss: 0.11124, Batch_BER: 0.07800\n",
      "Iteration: 360, Epoch: 3, Loss: 0.11116, Batch_BER: 0.10600\n",
      "Iteration: 370, Epoch: 3, Loss: 0.11121, Batch_BER: 0.09200\n",
      "Iteration: 380, Epoch: 3, Loss: 0.11122, Batch_BER: 0.10000\n",
      "Iteration: 390, Epoch: 3, Loss: 0.11133, Batch_BER: 0.09200\n",
      "Iteration: 400, Epoch: 3, Loss: 0.11158, Batch_BER: 0.09800\n",
      "Interim result for Epoch: 3, Loss: 0.11158, Batch_BER: 0.09800\n",
      "Training Bob in Epoch 4/4\n",
      "Iteration: 10, Epoch: 4, Loss: 0.11508, Batch_BER: 0.10400\n",
      "Iteration: 20, Epoch: 4, Loss: 0.11335, Batch_BER: 0.09000\n",
      "Iteration: 30, Epoch: 4, Loss: 0.11528, Batch_BER: 0.11600\n",
      "Iteration: 40, Epoch: 4, Loss: 0.11324, Batch_BER: 0.12400\n",
      "Iteration: 50, Epoch: 4, Loss: 0.11144, Batch_BER: 0.08000\n",
      "Iteration: 60, Epoch: 4, Loss: 0.11187, Batch_BER: 0.10400\n",
      "Iteration: 70, Epoch: 4, Loss: 0.11287, Batch_BER: 0.11000\n",
      "Iteration: 80, Epoch: 4, Loss: 0.11316, Batch_BER: 0.08000\n",
      "Iteration: 90, Epoch: 4, Loss: 0.11332, Batch_BER: 0.11000\n",
      "Iteration: 100, Epoch: 4, Loss: 0.11311, Batch_BER: 0.10200\n",
      "Iteration: 110, Epoch: 4, Loss: 0.11259, Batch_BER: 0.09600\n",
      "Iteration: 120, Epoch: 4, Loss: 0.11246, Batch_BER: 0.11200\n",
      "Iteration: 130, Epoch: 4, Loss: 0.11318, Batch_BER: 0.10400\n",
      "Iteration: 140, Epoch: 4, Loss: 0.11321, Batch_BER: 0.07400\n",
      "Iteration: 150, Epoch: 4, Loss: 0.11312, Batch_BER: 0.09600\n",
      "Iteration: 160, Epoch: 4, Loss: 0.11333, Batch_BER: 0.08600\n",
      "Iteration: 170, Epoch: 4, Loss: 0.11299, Batch_BER: 0.10400\n",
      "Iteration: 180, Epoch: 4, Loss: 0.11295, Batch_BER: 0.10600\n",
      "Iteration: 190, Epoch: 4, Loss: 0.11279, Batch_BER: 0.08400\n",
      "Iteration: 200, Epoch: 4, Loss: 0.11268, Batch_BER: 0.09400\n",
      "Iteration: 210, Epoch: 4, Loss: 0.11221, Batch_BER: 0.08600\n",
      "Iteration: 220, Epoch: 4, Loss: 0.11219, Batch_BER: 0.09600\n",
      "Iteration: 230, Epoch: 4, Loss: 0.11231, Batch_BER: 0.10800\n",
      "Iteration: 240, Epoch: 4, Loss: 0.11226, Batch_BER: 0.11800\n",
      "Iteration: 250, Epoch: 4, Loss: 0.11231, Batch_BER: 0.10400\n",
      "Iteration: 260, Epoch: 4, Loss: 0.11227, Batch_BER: 0.10600\n",
      "Iteration: 270, Epoch: 4, Loss: 0.11210, Batch_BER: 0.10400\n",
      "Iteration: 280, Epoch: 4, Loss: 0.11224, Batch_BER: 0.09200\n",
      "Iteration: 290, Epoch: 4, Loss: 0.11237, Batch_BER: 0.09800\n",
      "Iteration: 300, Epoch: 4, Loss: 0.11211, Batch_BER: 0.11400\n",
      "Iteration: 310, Epoch: 4, Loss: 0.11220, Batch_BER: 0.11000\n",
      "Iteration: 320, Epoch: 4, Loss: 0.11244, Batch_BER: 0.07800\n",
      "Iteration: 330, Epoch: 4, Loss: 0.11226, Batch_BER: 0.09200\n",
      "Iteration: 340, Epoch: 4, Loss: 0.11221, Batch_BER: 0.08200\n",
      "Iteration: 350, Epoch: 4, Loss: 0.11218, Batch_BER: 0.13800\n",
      "Iteration: 360, Epoch: 4, Loss: 0.11224, Batch_BER: 0.11400\n",
      "Iteration: 370, Epoch: 4, Loss: 0.11200, Batch_BER: 0.09400\n",
      "Iteration: 380, Epoch: 4, Loss: 0.11196, Batch_BER: 0.11400\n",
      "Iteration: 390, Epoch: 4, Loss: 0.11203, Batch_BER: 0.09600\n",
      "Iteration: 400, Epoch: 4, Loss: 0.11196, Batch_BER: 0.10200\n",
      "Interim result for Epoch: 4, Loss: 0.11196, Batch_BER: 0.10200\n",
      "Training Bob in Epoch 1/1\n",
      "Iteration: 10, Epoch: 1, Loss: 0.11092, Batch_BER: 0.11800\n",
      "Iteration: 20, Epoch: 1, Loss: 0.11652, Batch_BER: 0.11400\n",
      "Iteration: 30, Epoch: 1, Loss: 0.11197, Batch_BER: 0.08000\n",
      "Iteration: 40, Epoch: 1, Loss: 0.11206, Batch_BER: 0.09600\n",
      "Iteration: 50, Epoch: 1, Loss: 0.11081, Batch_BER: 0.10800\n",
      "Iteration: 60, Epoch: 1, Loss: 0.10953, Batch_BER: 0.09400\n",
      "Iteration: 70, Epoch: 1, Loss: 0.11007, Batch_BER: 0.07800\n",
      "Iteration: 80, Epoch: 1, Loss: 0.11033, Batch_BER: 0.08800\n",
      "Iteration: 90, Epoch: 1, Loss: 0.11044, Batch_BER: 0.08200\n",
      "Iteration: 100, Epoch: 1, Loss: 0.11007, Batch_BER: 0.11000\n",
      "Iteration: 110, Epoch: 1, Loss: 0.11002, Batch_BER: 0.11000\n",
      "Iteration: 120, Epoch: 1, Loss: 0.10993, Batch_BER: 0.08800\n",
      "Iteration: 130, Epoch: 1, Loss: 0.10939, Batch_BER: 0.08000\n",
      "Iteration: 140, Epoch: 1, Loss: 0.10933, Batch_BER: 0.09000\n",
      "Iteration: 150, Epoch: 1, Loss: 0.10909, Batch_BER: 0.09800\n",
      "Iteration: 160, Epoch: 1, Loss: 0.10936, Batch_BER: 0.11400\n",
      "Iteration: 170, Epoch: 1, Loss: 0.10954, Batch_BER: 0.09600\n",
      "Iteration: 180, Epoch: 1, Loss: 0.10922, Batch_BER: 0.08800\n",
      "Iteration: 190, Epoch: 1, Loss: 0.10921, Batch_BER: 0.09200\n",
      "Iteration: 200, Epoch: 1, Loss: 0.10980, Batch_BER: 0.11200\n",
      "Iteration: 210, Epoch: 1, Loss: 0.10959, Batch_BER: 0.11000\n",
      "Iteration: 220, Epoch: 1, Loss: 0.10946, Batch_BER: 0.10000\n",
      "Iteration: 230, Epoch: 1, Loss: 0.10953, Batch_BER: 0.10800\n",
      "Iteration: 240, Epoch: 1, Loss: 0.10991, Batch_BER: 0.10000\n",
      "Iteration: 250, Epoch: 1, Loss: 0.10955, Batch_BER: 0.09000\n",
      "Iteration: 260, Epoch: 1, Loss: 0.10964, Batch_BER: 0.09600\n",
      "Iteration: 270, Epoch: 1, Loss: 0.10961, Batch_BER: 0.10600\n",
      "Iteration: 280, Epoch: 1, Loss: 0.10971, Batch_BER: 0.09200\n",
      "Iteration: 290, Epoch: 1, Loss: 0.10971, Batch_BER: 0.11800\n",
      "Iteration: 300, Epoch: 1, Loss: 0.10967, Batch_BER: 0.09600\n",
      "Iteration: 310, Epoch: 1, Loss: 0.10960, Batch_BER: 0.11400\n",
      "Iteration: 320, Epoch: 1, Loss: 0.10942, Batch_BER: 0.10200\n",
      "Iteration: 330, Epoch: 1, Loss: 0.10945, Batch_BER: 0.09600\n",
      "Iteration: 340, Epoch: 1, Loss: 0.10936, Batch_BER: 0.09200\n",
      "Iteration: 350, Epoch: 1, Loss: 0.10940, Batch_BER: 0.09600\n",
      "Iteration: 360, Epoch: 1, Loss: 0.10935, Batch_BER: 0.11000\n",
      "Iteration: 370, Epoch: 1, Loss: 0.10947, Batch_BER: 0.10400\n",
      "Iteration: 380, Epoch: 1, Loss: 0.10951, Batch_BER: 0.10400\n",
      "Iteration: 390, Epoch: 1, Loss: 0.10948, Batch_BER: 0.10400\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Iteration: 400, Epoch: 1, Loss: 0.10965, Batch_BER: 0.09800\n",
      "Iteration: 410, Epoch: 1, Loss: 0.10951, Batch_BER: 0.09800\n",
      "Iteration: 420, Epoch: 1, Loss: 0.10949, Batch_BER: 0.10400\n",
      "Iteration: 430, Epoch: 1, Loss: 0.10941, Batch_BER: 0.08200\n",
      "Iteration: 440, Epoch: 1, Loss: 0.10931, Batch_BER: 0.07800\n",
      "Iteration: 450, Epoch: 1, Loss: 0.10939, Batch_BER: 0.11000\n",
      "Iteration: 460, Epoch: 1, Loss: 0.10936, Batch_BER: 0.12200\n",
      "Iteration: 470, Epoch: 1, Loss: 0.10927, Batch_BER: 0.10000\n",
      "Iteration: 480, Epoch: 1, Loss: 0.10921, Batch_BER: 0.12000\n",
      "Iteration: 490, Epoch: 1, Loss: 0.10924, Batch_BER: 0.10600\n",
      "Iteration: 500, Epoch: 1, Loss: 0.10922, Batch_BER: 0.08800\n",
      "Interim result for Epoch: 1, Loss: 0.10922, Batch_BER: 0.08800\n"
     ]
    }
   ],
   "source": [
    "score_fn = NN_function(**critic_params)\n",
    "train_mi(score_fn, n_epochs=1, n_steps=500, batch_size=64)\n",
    "train_encoder(score_fn, n_epochs=5, n_steps=400, batch_size=64, learning_rate=0.005)\n",
    "test_encoding(M, 1)\n",
    "train_encoder(score_fn, n_epochs=5, n_steps=400, batch_size=64, learning_rate=0.001)\n",
    "test_encoding(M, 1)\n",
    "train_decoder(n_epochs=5, n_steps=400, batch_size=500, learning_rate=0.015, plot_encoding=False)\n",
    "train_decoder(n_epochs=4, n_steps=400, batch_size=500, learning_rate=0.01, plot_encoding=False)\n",
    "train_decoder(n_epochs=1, n_steps=500, batch_size=500, learning_rate=0.005, plot_encoding=False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Progress: 6 of 30 parts\n",
      "Progress: 12 of 30 parts\n",
      "Progress: 18 of 30 parts\n",
      "Progress: 24 of 30 parts\n",
      "Progress: 30 of 30 parts\n"
     ]
    }
   ],
   "source": [
    "bber_data = Test_AE()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 576x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Approximate 16 QAM Error\n",
    "def SIXT_QAM_sim(ebnodb):\n",
    "    ebno = 10.**(ebnodb/10)\n",
    "    return (3.0/2)*special.erfc(np.sqrt((4.0/10)*ebno))\n",
    "\n",
    "def QAM_pb(ebnodb):\n",
    "    ebno = 10.**(ebnodb/10)\n",
    "    return (4/np.log2(M))*special.erfc(np.sqrt((3*ebno*np.log2(M))/(M-1)))\n",
    "\n",
    "ebnodbs = np.linspace(0,15,16)\n",
    "fig = plt.figure(figsize=(8, 5))\n",
    "plt.semilogy(bber_data[0], bber_data[1], 'o-')\n",
    "\n",
    "plt.semilogy(ebnodbs, SIXT_QAM_sim(ebnodbs), '^-');\n",
    "plt.gca().set_ylim(1e-5, 1)\n",
    "plt.gca().set_xlim(0, 15)\n",
    "plt.ylabel(\"Batch Symbol Error Rate\", fontsize=14, rotation=90)\n",
    "plt.xlabel(\"EbN0 [dB]\", fontsize=18)\n",
    "plt.legend(['AE with MINE', '16QAM'],\n",
    "           prop={'size': 14}, loc='upper right');\n",
    "plt.grid(True, which=\"both\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
